package com.xy.exam.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * JWT工具类 - 简化版
 * 集成Redis缓存token
 */
@Component
public class JwtUtil {

    @Value("${jwt.secret}")
    private String secretKey;

    @Value("${jwt.expiration}")
    private long jwtExpiration;
    
    private final RedisTemplate<String, Object> redisTemplate;
    
    // Redis Token前缀
    private static final String TOKEN_PREFIX = "token:";
    
    public JwtUtil(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 生成JWT令牌
     * @param username 用户名
     * @return 生成的JWT令牌
     */
    public String generateToken(String username) {
        Map<String, Object> claims = new HashMap<>();
        String token = Jwts.builder()
                .setClaims(claims)
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + jwtExpiration))
                .signWith(getSigningKey(), SignatureAlgorithm.HS256)
                .compact();
        
        // 将令牌存入Redis，设置相同的过期时间
        String redisKey = TOKEN_PREFIX + username;
        redisTemplate.opsForValue().set(redisKey, token, jwtExpiration, TimeUnit.MILLISECONDS);
        
        return token;
    }

    /**
     * 从Redis中验证并获取令牌
     * @param username 用户名
     * @param token JWT令牌
     * @return 是否有效
     */
    public boolean validateToken(String username, String token) {
        // 从Redis获取存储的token
        String redisKey = TOKEN_PREFIX + username;
        Object storedToken = redisTemplate.opsForValue().get(redisKey);
        
        if (storedToken == null || !storedToken.toString().equals(token)) {
            return false;
        }
        
        // 进一步验证token是否过期
        try {
            Claims claims = extractAllClaims(token);
            return claims.getExpiration().after(new Date());
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 从Redis中删除令牌（登出）
     * @param username 用户名
     */
    public void invalidateToken(String username) {
        String redisKey = TOKEN_PREFIX + username;
        redisTemplate.delete(redisKey);
    }

    /**
     * 从令牌中提取用户名
     * @param token JWT令牌
     * @return 用户名
     */
    public String extractUsername(String token) {
        return extractAllClaims(token).getSubject();
    }

    private Claims extractAllClaims(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(getSigningKey())
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    private Key getSigningKey() {
        byte[] keyBytes = Decoders.BASE64.decode(secretKey);
        return Keys.hmacShaKeyFor(keyBytes);
    }
} 